package com.zhuanzhuan.hero.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bj58.youpin.common.utils.json.JsonUtils;
import com.bj58.zhuanzhuan.zzentry.common.service.entity.ServiceHeaderEntity;
import com.zhuanzhuan.hero.member.enums.AuthCodeEnum;
import com.zhuanzhuan.hero.user.annotations.EncryptedMethod;
import com.zhuanzhuan.hero.user.consts.NumConsts;
import com.zhuanzhuan.hero.user.entity.HeroUserAuthentication;
import com.zhuanzhuan.hero.user.entity.HeroUserInfo;
import com.zhuanzhuan.hero.user.enums.ExceptionMsgEnum;
import com.zhuanzhuan.hero.user.enums.StateEnum;
import com.zhuanzhuan.hero.user.enums.UserStateEnum;
import com.zhuanzhuan.hero.user.exception.BusinessException;
import com.zhuanzhuan.hero.user.helper.HeroMemberHelper;
import com.zhuanzhuan.hero.user.helper.SpamlogicHeleper;
import com.zhuanzhuan.hero.user.mapper.HeroUserInfoMapper;
import com.zhuanzhuan.hero.user.mq.dto.MemberEventMsg;
import com.zhuanzhuan.hero.user.pojo.bo.QueryUserInfoParam;
import com.zhuanzhuan.hero.user.pojo.po.UserPO;
import com.zhuanzhuan.hero.user.service.HeroUserAuthenticationService;
import com.zhuanzhuan.hero.user.service.HeroUserInfoService;
import com.zhuanzhuan.hero.user.service.IApolloService;
import com.zhuanzhuan.hero.user.util.DesensitizeUtil;
import com.zhuanzhuan.hero.user.util.ServiceHeaderUtil;
import com.zhuanzhuan.hero.user.vo.UserRealPersonAuthInfoVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * dal Interface:HeroUserInfo
 * @author hanjunjun
 * @date 2024-6-17
 */
@Service
@Slf4j
public class HeroUserInfoServiceImpl extends ServiceImpl<HeroUserInfoMapper, HeroUserInfo> implements HeroUserInfoService{

    @Autowired
    private HeroUserInfoMapper heroUserInfoMapper;

    @Resource
    private SpamlogicHeleper spamlogicHeleper;

    @Resource
    private HeroUserAuthenticationService userAuthenticationService;

    @Resource
    private IApolloService apolloService;

    @Resource
    private HeroMemberHelper heroMemberHelper;

    @Override
    public HeroUserInfo getUserByUid(Long uid) {
        HeroUserInfo query = new HeroUserInfo();
        query.setUid(uid);
        query.setState(StateEnum.EFFECTIVE.getCode());
        List<HeroUserInfo> list = heroUserInfoMapper.select(query);
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }

        return list.get(0);
    }

    @Override
    public List<HeroUserInfo> listByUid(List<Long> uids) {
        if (CollectionUtils.isEmpty(uids)) {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<HeroUserInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(HeroUserInfo::getUid, uids)
            .eq(HeroUserInfo::getState, StateEnum.EFFECTIVE.getCode());
        return this.list(queryWrapper);
    }

    @EncryptedMethod
    @Override
    public List<UserPO> listByParam(QueryUserInfoParam param) {
        log.info("listByParam param={}", JsonUtils.toJsonWithoutNull(param));
        return getBaseMapper().selectByParam(param);
    }

    @Override
    public void updateByUid(Long uid, HeroUserInfo heroUserInfoUpdate) {
        if (Objects.isNull(heroUserInfoUpdate)) {
            log.error("更新参数为空");
            throw new BusinessException("更新参数不可为空");
        }
        LambdaUpdateWrapper<HeroUserInfo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(HeroUserInfo::getUid, uid)
            .eq(HeroUserInfo::getState, StateEnum.EFFECTIVE.getCode());

        heroUserInfoMapper.update(heroUserInfoUpdate, updateWrapper);
    }

    @Override
    public HeroUserInfo getByPrimaryKey(Long key){
        return heroUserInfoMapper.getByPrimaryKey(key);
    }

    @Override
    public Long insertSelective(HeroUserInfo record){
        return heroUserInfoMapper.insertSelective(record);

    }

    @Override
    public Integer updateByPrimaryKey(HeroUserInfo record){
        return heroUserInfoMapper.updateByPrimaryKey(record);
    }

    @Override
    public List<UserRealPersonAuthInfoVO> queryAllRealPersonAuthUserInfo(Long uid) {
        Set<Long> allUid = spamlogicHeleper.getSameIdCardAllUid(uid);
        if (CollectionUtils.isEmpty(allUid)) {
            return new ArrayList<>();
        }

        ArrayList<Long> uidList = new ArrayList<>(allUid);
        //查询用户信息
        List<HeroUserInfo> userInfos = this.listByUid(uidList);
        if (CollectionUtils.isEmpty(userInfos)) {
            return new ArrayList<>();
        }
        //查询认证信息
        List<HeroUserAuthentication> userAuthentications = userAuthenticationService.listByUid(uidList);
        Map<Long, HeroUserAuthentication> userAuthenticationMap =
            userAuthentications.stream().collect(Collectors.toMap(HeroUserAuthentication::getUid, Function.identity()));

        return userInfos.stream()
            .map(userInfo -> this.convertUserRealPersonAuthInfoVO(userInfo, userAuthenticationMap))
            .collect(Collectors.toList());
    }

    @Override
    public void checkCanEdit(Long uid) {
        if (Objects.isNull(uid)) {
            throw new BusinessException(ExceptionMsgEnum.PARAM_ERROR);
        }
        //会员超时未续费、会员已主动退出、被清退不可编辑
        if (!heroMemberHelper.hasAuth(uid, AuthCodeEnum.EDIT_PROFILE.getCode())) {
            throw new BusinessException(ExceptionMsgEnum.CAN_NOT_EDIT);
        }
    }

    @Override
    public boolean baseInfoIsPerfection(Long uid, HeroUserInfo userInfo) {
        if (Objects.isNull(uid) && Objects.isNull(userInfo)) {
            throw new BusinessException(ExceptionMsgEnum.PARAM_ERROR);
        }
        if (Objects.isNull(userInfo)) {
            userInfo = this.getUserByUid(uid);
        }

        if (StringUtils.isBlank(userInfo.getNickname())) {
            return false;
        }
        if (StringUtils.isBlank(userInfo.getCompanyPosition())) {
            return false;
        }

        return true;
    }

    @Override
    public boolean unregistUser(Long uid) {
        LambdaUpdateWrapper<HeroUserInfo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(HeroUserInfo::getUserState, UserStateEnum.UNREGISTERED.getCode())
            .eq(HeroUserInfo::getUid, uid)
            .eq(HeroUserInfo::getState, StateEnum.EFFECTIVE.getCode());
        return this.update(updateWrapper);
    }

    @Override
    public boolean needHideMemberLevel(ServiceHeaderEntity header) {
        if (Objects.isNull(header)) {
            //首页列表没登录则不隐藏
            return false;
        }
        String version = ServiceHeaderUtil.parseVsersion(header);
        if (StringUtils.isBlank(version)) {
            return false;
        }

        return version.equals(apolloService.queryIosVirtualLoginVer());
    }

    @Override
    public boolean updateMemberInfo(MemberEventMsg body) {
        log.info("updateMemberInfo param={}", JsonUtils.toJsonWithoutNull(body));
        HeroUserInfo userInfo = this.getUserByUid(body.getUid());
        if (Objects.isNull(userInfo)) {
            log.info("查询用户为空");
            return true;
        }
        if (UserStateEnum.UNREGISTERED.getCode().equals(userInfo.getUserState())) {
            log.info("用户已注销");
            return true;
        }

        LambdaUpdateWrapper<HeroUserInfo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(HeroUserInfo::getId, userInfo.getId()).set(HeroUserInfo::getUpdateBy, NumConsts.SYSTEM_CODE);
        Integer eventType = body.getEventType();
        if (NumConsts.ONE.equals(eventType)) {
            log.info("开通会员");
            updateWrapper.set(HeroUserInfo::getUserState, UserStateEnum.SETTLED.getCode())
                .set(HeroUserInfo::getMemberLevel, body.getMemberLevel())
                .set(HeroUserInfo::getSettleTime, new Date(body.getFirstActivateTime()));
        } else if (NumConsts.TWO.equals(eventType)) {
            log.info("会员过期");
            //状态更新成【已过期】,等级清空不能再被运营后台筛选到
            updateWrapper.set(HeroUserInfo::getUserState, UserStateEnum.EXPIRED.getCode())
                .set(HeroUserInfo::getMemberLevel, null);
        } else if (NumConsts.THREE.equals(eventType)) {
            log.info("会员续费");
            updateWrapper.set(HeroUserInfo::getUserState, UserStateEnum.SETTLED.getCode())
                .set(HeroUserInfo::getMemberLevel, body.getMemberLevel());
        } else if (NumConsts.FOUR.equals(eventType)) {
            log.info("会员升级");
            updateWrapper.set(HeroUserInfo::getUserState, UserStateEnum.SETTLED.getCode())
                .set(HeroUserInfo::getMemberLevel, body.getMemberLevel());
        } else if (NumConsts.FIVE.equals(eventType)) {
            log.info("主动退出");
            updateWrapper.set(HeroUserInfo::getUserState, UserStateEnum.EXITED.getCode())
                .set(HeroUserInfo::getMemberLevel, null);
        } else if (NumConsts.SIX.equals(eventType)) {
            log.info("清退");
            updateWrapper.set(HeroUserInfo::getUserState, UserStateEnum.EXPELLED.getCode())
                .set(HeroUserInfo::getMemberLevel, null);
        } else {
            log.info("参数错误");
            return true;
        }

        this.update(updateWrapper);
        return true;
    }

    private UserRealPersonAuthInfoVO convertUserRealPersonAuthInfoVO(HeroUserInfo userInfo, Map<Long, HeroUserAuthentication> userAuthenticationMap) {
        UserRealPersonAuthInfoVO vo = new UserRealPersonAuthInfoVO();
        vo.setUid(userInfo.getUid());
        //注册的手机号   脱敏
        vo.setRegistMobile(DesensitizeUtil.desensitizeMobile(userInfo.getMobile()));
        HeroUserAuthentication userAuthentication = userAuthenticationMap.get(userInfo.getUid());
        if (Objects.nonNull(userAuthentication)) {
            vo.setRealPersonName(userAuthentication.getRealName());
        }
        return vo;
    }
}